package com.holly.unit.deform.designer.core.table;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.holly.unit.deform.designer.entity.CreateTable;
import com.holly.unit.deform.designer.entity.CreateTableField;
import com.holly.unit.deform.designer.enums.TableHandleEnum;
import com.holly.unit.deform.designer.kit.StrKit;
import com.holly.unit.deform.designer.pojo.dto.CreateTableDTO;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 类描述: MySQL的表数据定义语言实现
 *
 * @author fxr
 * @version 1.0.0
 * @date 2022/7/23 10:02
 */
public class MySQLDbTableDDLImpl extends DbTableDDLBase implements IDbTableDDL{

    @Override
    public String createTable(CreateTableDTO createTableDTO) {
        String createDDL = this.CREATE_DDL.replace("${table}", createTableDTO.getTable().getTableName());
        StringBuilder sb = new StringBuilder();
        List<CreateTableField> fields = createTableDTO.getFields();
        for (CreateTableField field : fields) {
            if(FIELD_ID.equals(field.getFieldName())) {
                continue;
            }
            sb.append(field.getFieldName()+" ");
            sb.append(getDataType(field));
            sb.append(",");
        }
        //去掉组合语句时多余的那个逗号","
        sb.delete(sb.length()-1, sb.length());
        return createDDL.replace("${fields}", sb.toString());
    }

    /***
     * 更新表结构
     * @param createTableDTO
     * @return
     */
    @Override
    public List<String> alertTable(CreateTableDTO createTableDTO) {

        List<String> res = new ArrayList<>();
        if (null == createTableDTO || null == createTableDTO.getTable()
                || null == createTableDTO.getFields() || createTableDTO.getFields().size()<1) {
            return null;
        }
        //获取老表
        CreateTable oldTable = createTableService.getById(createTableDTO.getTable().getId());
        if (ObjectUtil.isNull(oldTable)) {
            return null;
        }
        //获取老表中的字段
        QueryWrapper<CreateTableField> wrapper = new QueryWrapper<>();
        wrapper.eq("tableId",createTableDTO.getTable().getId());
        List<CreateTableField> oldFields = tableFieldService.list(wrapper);
        if (ObjectUtil.isNull(oldFields)) {
            return null;
        }

        //处理字段信息
        Map<String,List<CreateTableField>> mapFields = handleTableAndFields(createTableDTO,oldTable,oldFields);
        // 把新的数据更新到老的对象中
        oldTable.setTableName(createTableDTO.getTable().getTableName());
        oldTable.setRemark(createTableDTO.getTable().getRemark());
        // 更新表信息
        boolean b = createTableService.updateById(oldTable);
        if (!b) {// 更新失败
            throw new RuntimeException("更新数据失败");
        }
        // 判断表是否需要修改
        String alertTable = oldTable.getChangeTable();
        res.add(alertTable);
        if(null != mapFields && mapFields.size() > 0) {
            //获取处理后的字段信息
            List<CreateTableField> fields = null;
            for(String key : mapFields.keySet()) {
                fields = mapFields.get(key);
                if(TableHandleEnum.TABLE_FIELD_UPDATE_FLAG.fieldName().equals(key)) { //修改字段
                    tableFieldService.updateBatchById(fields);
                } else if(TableHandleEnum.TABLE_FIELD_NEW_FLAG.fieldName().equals(key)) { //添加字段
                    tableFieldService.saveBatch(fields);
                } else if(TableHandleEnum.TABLE_FIELD_DEL_FLAG.fieldName().equals(key)) { //删除字段
                    tableFieldService.removeByIds(fields);
                }
                for (CreateTableField field : fields) {
                    String[] sqls = field.getChangeFields().toString().split(";");
                    for (int i = 0; i < sqls.length; i++) {
                        res.add(sqls[i]);
                    }
                }
            }
        }

        return res;
    }

    @Override
    public String dropTable() {

        return null;
    }



    /***
     * 根据数据类型和长度，组合成DDL语句的数据类型
     * @param field
     * @return
     */
    private String getDataType(CreateTableField field) {
        StringBuffer fieldBuf = new StringBuffer();
        if(DATA_FORMAT_VARCHAR.equals(field.getDataFormat())) {
            fieldBuf.append(" "+field.getDataFormat()+"(");
            if(!StrKit.isNum(field.getLen()) || StrUtil.isEmpty(field.getLen())) {
                fieldBuf.append("50");
                field.setLen("50");
            } else {
                String num = Double.parseDouble(field.getLen())>4000?"4000":field.getLen();
                fieldBuf.append(num);
                field.setLen(num);
            }
            fieldBuf.append(")");
        } else if(DATA_FORMAT_INT.equals(field.getDataFormat())) {
            fieldBuf.append(" "+field.getDataFormat()+"(");
            if(StrKit.isNum(field.getLen()) || StrUtil.isEmpty(field.getLen())) {
                fieldBuf.append("5");
                field.setLen("5");
            } else {
                String num = Double.parseDouble(field.getLen())>11?"11":field.getLen();
                fieldBuf.append(num);
                field.setLen(num);
            }
            fieldBuf.append(")");
        } else if(DATA_FORMAT_NUMERIC.equals(field.getDataFormat())) {
            fieldBuf.append(" "+field.getDataFormat()+"(");
            if(!StrKit.isCheckRegex(field.getLen(),"\\d+,\\d+") || StrUtil.isEmpty(field.getLen())) {
                fieldBuf.append("8,3");
                field.setLen("8,3");
            } else {
                String[] values = field.getLen().split(",");
                String num1 = null;
                String num2 = null;
                if(values.length==2) {
                    int n1 = Integer.parseInt(values[0]);
                    int n2 = Integer.parseInt(values[1]);
                    n1 = n1 > 50 ? 50 : n1;
                    n2 = n2 > 10 ? 10 : n2;
                    num1 = String.valueOf(n1);
                    num2 = String.valueOf(n2);
                } else {
                    int n1 = Integer.parseInt(values[1]);
                    n1 = n1 > 50 ? 50 : n1;
                    num1 = String.valueOf(n1);
                    num2 = "3";
                }
                fieldBuf.append(num1+","+num2);
                field.setLen(num1+","+num2);
            }
            fieldBuf.append(")");
        } else if(DATA_FORMAT_DATETIME.equals(field.getDataFormat())) {
            fieldBuf.append(" datetime ");
        } else if(DATA_FORMAT_TEXT.equals(field.getDataFormat())) {
            fieldBuf.append(" "+field.getDataFormat()+" ");
        } else if(DATA_FORMAT_LONG_TEXT.equals(field.getDataFormat())) {
            fieldBuf.append(" "+field.getDataFormat()+" ");
        }

        return fieldBuf.toString();
    }

    /***
     * 处理字段
     * @param tableData 外界传入参数
     * @param table
     * @param oldFields
     * @return
     */
    private Map<String,List<CreateTableField>> handleTableAndFields(CreateTableDTO tableData,CreateTable table, List<CreateTableField> oldFields) {

        Map<String,List<CreateTableField>> tableFieldMaps = null;
        if(null != oldFields && oldFields.size()>0 && null != tableData
                && null !=tableData.getFields() && tableData.getFields().size()>0 && null != table) {
            tableFieldMaps = new HashMap<>();
            List<CreateTableField> newList = new ArrayList<>();
            for (CreateTableField newField : tableData.getFields()) {
                if (ObjectUtil.isEmpty(newField.getId()) && StrUtil.isNotEmpty(newField.getFieldName())) {
                    newField.getChangeFields().append("alter table "+tableData.getTable().getTableName()+" add "+newField.getFieldName()+" "+getDataType(newField));
                    newField.setTableId(table.getId()+"");
                    newList.add(newField);
                }
            }
            // 判断表名是否修改
            if(table.getId().equals(tableData.getTable().getId()) && !table.getTableName().equals(tableData.getTable().getTableName())) {
                table.setChangeTable("RENAME TABLE "+table.getTableName()+" TO "+tableData.getTable().getTableName());
            }
            if(newList.size()>0)
                tableFieldMaps.put(TableHandleEnum.TABLE_FIELD_NEW_FLAG.fieldName(), newList);
            List<CreateTableField> delList = new ArrayList<>();
            List<CreateTableField> updateList = new ArrayList<>();
            for (CreateTableField oldField : oldFields) {
                boolean isExist = false; //判断以前字段中是否存在修改后的这个字段
                boolean isChange = false; //判断字段是否改变(以前字段与修改后的字段对比)
                for (CreateTableField newField : tableData.getFields()) {
                    if(ObjectUtil.isEmpty(newField.getId())) {
                        continue;
                    }
                    if(oldField.getId().equals(newField.getId())) {
                        isExist = true;
                        if(!oldField.isSame(newField)) {
                            if(!oldField.isNameSame(newField)) {
                                oldField.getChangeFields().append("alter table "+tableData.getTable().getTableName()+" change column "+oldField.getFieldName()+" "+newField.getFieldName()+" "+getDataType(oldField)+";");
                                isChange = true;
                            }
                            if(!oldField.isDataFormatSame(newField)) {
                                String dataType = getDataType(newField);
                                oldField.getChangeFields().append("alter table "+tableData.getTable().getTableName()+" modify column "+newField.getFieldName()+" "+dataType+";");
                                isChange = true;
                            } else if(!oldField.isLengthSame(newField)) {
                                String dataType = getDataType(newField);
                                oldField.getChangeFields().append("alter table "+tableData.getTable().getTableName()+" modify column "+newField.getFieldName()+" "+dataType+";");
                                isChange = true;
                            } else if(!oldField.isRemart(newField)) {
                                isChange = true;
                            }
                            if(isChange) {
                                oldField.setFieldName(newField.getFieldName());
                                oldField.setDataFormat(newField.getDataFormat());
                                oldField.setFieldRemark(newField.getFieldRemark());
                                oldField.setLen(newField.getLen());
                            }
                        }
                        if(isChange) {
                            updateList.add(oldField);
                        }
                        break;
                    }//if
                }//for
                if(!isExist) {
                    oldField.getChangeFields().append("alter table "+tableData.getTable().getTableName()+" drop column "+oldField.getFieldName());
                    delList.add(oldField);
                }
            }//for
            if(delList.size()>0) {
                tableFieldMaps.put(TableHandleEnum.TABLE_FIELD_DEL_FLAG.fieldName(), delList);
            }
            if(updateList.size()>0) {
                tableFieldMaps.put(TableHandleEnum.TABLE_FIELD_UPDATE_FLAG.fieldName(), updateList);
            }
        }
        return tableFieldMaps;
    }



}
